/* 
    深拷贝
*/
// 1 JSON 不能克隆方法 不能循环引用 
function deepClone(target) {
    // 通过数据创建JSON格式字符串
    let str = JSON.stringify(target);
    // 将JSON字符串创建为js数据
    let data = JSON.parse(str);
    // console.log(data);
    return data;
}

// 2 递归深拷贝 不能解决循环引用 栈溢出
function deepClone2(target) {
    // 检测数据类型
    if (typeof target === 'object' && target !== null) {
        // 创建一个容器
        let result = Array.isArray(target) ? [] : {};
        // 遍历对象
        for (let key in target) {
            // 检测该属性是否为对象本身的属性(不能拷贝原型对象上的属性)
            if (target.hasOwnProperty(key)) {
                // 拷贝
                result[key] = deepClone2(target[key])
            }
        }
        return result;
    } else {
        return target;
    }
}
// 解决循环引用
function deepClone3(target, map = new Map()) {
    // 检测数据类型
    if (typeof target === 'object' && target !== null) {
        // 克隆数据之前 判断数据之前是否克隆过
        let cache = map.get(target);
        if (cache) {
            return cache;
        }
        // 创建一个容器
        let result = Array.isArray(target) ? [] : {};
        // 将新的结果存入到map中
        map.set(target, result);
        // 遍历对象
        for (let key in target) {
            // 检测该属性是否为对象本身的属性(不能拷贝原型对象上的属性)
            if (target.hasOwnProperty(key)) {
                // 拷贝
                result[key] = deepClone3(target[key], map)
            }
        }
        return result;
    } else {
        return target;
    }
}

// 遍历性能优化
function deepClone4(target, map = new Map()) {
    // 检测数据类型
    if (typeof target === 'object' && target !== null) {
        // 克隆数据之前 判断数据之前是否克隆过
        let cache = map.get(target);
        if (cache) {
            return cache;
        }
        // 创建一个容器
        let isArray = Array.isArray(target)
        let result = isArray ? [] : {};
        // 将新的结果存入到map中
        map.set(target, result);
        // 遍历对象
        // 如果目标对象是数组
        if (isArray) {
            // forEach
            target.forEach((item, index) => {
                result[index] = deepClone4(item, map);
            });
        } else {
            // 如果是对象
            Object.keys(target).forEach(key => {
                result[key] = deepClone4(target[key], map);
            })
        }
        return result;
    } else {
        return target;
    }
}